﻿using System;
using System.Text;
using System.Web;
using System.IO;
using System.Net;
using System.Text.RegularExpressions;

namespace CoolCode.Web
{
    public class CompressionHandler : IHttpHandler
    {
        private HttpContext context;

        #region IHttpHandler Members

        public bool IsReusable
        {
            get { return true; }
        }

        public void ProcessRequest(HttpContext context)
        {
            this.context = context;
            string name = context.Request.QueryString["name"];
            throw new NotImplementedException("CompressionHandler handle file path!");
            if (name != null && (name.EndsWith(".js", StringComparison.OrdinalIgnoreCase) || name.EndsWith(".css", StringComparison.OrdinalIgnoreCase)))
            {
                string text = (string)context.Cache[name.ToLower()];

                string ContentType = SetContentType(name);

                if (text == null)
                {
                    using (StreamReader sr = new StreamReader(context.Server.MapPath(name)))
                    {
                        text = sr.ReadToEnd();
                        sr.Close();
                    }
                    if (ContentType == "text/javascript")
                    {
                        text = StripWhitespaceJs(text);
                    }
                    else if (ContentType == "text/css")
                    {
                        text = StripWhitespaceCss(text);
                    }
                    context.Cache.Add(name, text, new System.Web.Caching.CacheDependency(context.Server.MapPath(name)),
                        DateTime.MaxValue, TimeSpan.Zero, System.Web.Caching.CacheItemPriority.High, null);
                }
                context.Response.Clear();
                SetHeaders(name, ContentType);
                context.Response.Write(text);
                context.Response.End();
            }
        }

        #endregion

        private string SetContentType(string name)
        {
            string ContentType = "text/css";
            if (name.EndsWith(".js", StringComparison.OrdinalIgnoreCase))
            {
                ContentType = "text/javascript";
            }
            else if (name.EndsWith(".css", StringComparison.OrdinalIgnoreCase))
            {
                ContentType = "text/css";
            }
            return ContentType;
        }

        private void SetHeaders(string file, string ContentType)
        {
            context.Response.ContentType = ContentType;
            context.Response.Cache.VaryByHeaders["Accept-Encoding"] = true;

            DateTime date = DateTime.Now;
            if (context.Cache[file + "date"] != null)
                date = (DateTime)context.Cache[file + "date"];

            string etag = "\"" + date.GetHashCode() + "\"";
            string incomingEtag = context.Request.Headers["If-None-Match"];

            context.Response.Cache.SetExpires(DateTime.Now.ToUniversalTime().AddDays(7));
            context.Response.Cache.SetCacheability(HttpCacheability.Public);
            context.Response.Cache.SetMaxAge(new TimeSpan(7, 0, 0, 0));
            context.Response.Cache.SetRevalidation(HttpCacheRevalidation.AllCaches);
            context.Response.Cache.SetETag(etag);

            if (String.Compare(incomingEtag, etag) == 0)
            {
                context.Response.StatusCode = (int)HttpStatusCode.NotModified;
                context.Response.End();
            }
        }

        private string StripWhitespaceJs(string body)
        {
            string[] lines = body.Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);
            StringBuilder sb = new StringBuilder();
            foreach (string line in lines)
            {
                string s = line.Trim();
                if (s.Length > 0 && !s.StartsWith("//"))
                    sb.AppendLine(s.Trim());
            }

            body = sb.ToString();
            body = Regex.Replace(body, @"^[\s]+|[ \f\r\t\v]+$", String.Empty);
            body = Regex.Replace(body, @"([+-])\n\1", "$1 $1");
            body = Regex.Replace(body, @"([^+-][+-])\n", "$1");
            body = Regex.Replace(body, @"([^+]) ?(\+)", "$1$2");
            body = Regex.Replace(body, @"(\+) ?([^+])", "$1$2");
            body = Regex.Replace(body, @"([^-]) ?(\-)", "$1$2");
            body = Regex.Replace(body, @"(\-) ?([^-])", "$1$2");
            body = Regex.Replace(body, @"\n([{}()[\],<>/*%&|^!~?:=.;+-])", "$1");
            body = Regex.Replace(body, @"(\W(if|while|for)\([^{]*?\))\n", "$1");
            body = Regex.Replace(body, @"(\W(if|while|for)\([^{]*?\))((if|while|for)\([^{]*?\))\n", "$1$3");
            body = Regex.Replace(body, @"([;}]else)\n", "$1 ");
            body = Regex.Replace(body, @"(?<=[>])\s{2,}(?=[<])|(?<=[>])\s{2,}(?=&nbsp;)|(?<=&ndsp;)\s{2,}(?=[<])", String.Empty);

            return body;
        }

        private string StripWhitespaceCss(string body)
        {
            body = body.Replace("  ", String.Empty);
            body = body.Replace(Environment.NewLine, String.Empty);
            body = body.Replace("\t", string.Empty);
            body = body.Replace(" {", "{");
            body = body.Replace(" :", ":");
            body = body.Replace(": ", ":");
            body = body.Replace(", ", ",");
            body = body.Replace("; ", ";");
            body = body.Replace(";}", "}");
            //body = Regex.Replace(body, @"/\*[^\*]*\*+([^/\*]*\*+)*/", "$1");
            body = Regex.Replace(body, @"(?<=[>])\s{2,}(?=[<])|(?<=[>])\s{2,}(?=&nbsp;)|(?<=&ndsp;)\s{2,}(?=[<])", String.Empty);

            return body;
        }

    }
}
